#include "LifeBoardTest.h"
#include <iostream>

using namespace std;

      LifeBoardTest::LifeBoardTest(){
        testBoard = new LifeBoard(3,4);
      }

      LifeBoardTest::~LifeBoardTest(){
        testBoard->~LifeBoard();
        delete &testBoard;
      }

      //checks that the x range is being returned correctly.
      //returns a true if it is and a false if it isn't
      bool LifeBoardTest::returnXRangeCorr(){
        if(!this->returnXRangeCorrError()){return false;}

        return true;
      }

      //checks that the y range is being returned correctly.
      //returns a true if it is and a false if it isn't
      bool LifeBoardTest::returnYRangeCorr(){

        if(!this->returnYRangeCorrError()){return false;}

        return true;
      }

      //checks to see if the board was in fact reset to 0
      //returns true if all 0's and false if any other number
      bool LifeBoardTest::resetGrid(){
        if(!this->resetGridError()){return false;}

        return true;
      }

      //checks the setLifeBoard() function.
      //should be set to value specified when passing function
      //or else sends false
      bool LifeBoardTest::setValueTest(){
        //LifeBoard testBoard(3,4);

        //sets value at location (1,1). Should be 1.
        testBoard->setLifeBoard(1, 1, 1);
        if(!this->setValueTestError(1, 1, 1)) {return false;}

        //resets value at (1, 1) from previous test. Should be 0.
        testBoard->setLifeBoard(0, 1, 1);
        if(!this->setValueTestError(0, 1, 1)) {return false;}

        //sets value at location 1, 1 then resets board. Should be 0.
        testBoard->setLifeBoard(1, 1, 1);
        testBoard->resetLifeBoard();
        if(!this->setValueTestError(0, 1, 1)) {return false;}

        //sets value at the limit of x range. Should be 1.
        testBoard->setLifeBoard(1, testBoard->getLifeBoardXRange() - 1, 0);
        if(!this->setValueTestError(1, testBoard->getLifeBoardXRange() - 1, 0)) {return false;}

        //sets value at the limit of y range. Should Be 1.
        testBoard->setLifeBoard(1, 0, testBoard->getLifeBoardYRange() - 1);
        if(!this->setValueTestError(1, 0, testBoard->getLifeBoardYRange() - 1)) {return false;}

        //testBoard.~LifeBoard();
        return true;
      }

      //checks to see if the copy function will copy the exact value
      //of the game board to another LifeBoard class
      //returns true if it succeeds and a false if it fails
      bool LifeBoardTest::copyTest(){
        int xRangeOfBoard = testBoard->getLifeBoardXRange();
        int yRangeOfBoard = testBoard->getLifeBoardYRange();
        LifeBoard * copyBoard = new LifeBoard(xRangeOfBoard, yRangeOfBoard);

        //tests when board is empty
        testBoard->resetLifeBoard();
        copyBoard->copy(testBoard);
        if(!this->copyTestError(copyBoard, xRangeOfBoard, yRangeOfBoard)){
            copyBoard->~LifeBoard();
            return false;
        }

        //check when board is all 1's
        fillLifeBoardOnes();
        copyBoard->copy(testBoard);
        if(!this->copyTestError(copyBoard, xRangeOfBoard, yRangeOfBoard)){
            copyBoard->~LifeBoard();
            return false;
        }

        //tests when board has select values (5 tests)
        //1. Alternating
        //2. Value set at end of X Range
        //3. Value set at end of Y Range
        //4. Value set at beginning of X Range and Y Range

        /***1***/
        fillLifeBoardAlt();
        copyBoard->copy(testBoard);
        if(!this->copyTestError(copyBoard, xRangeOfBoard, yRangeOfBoard)){
            copyBoard->~LifeBoard();
            return false;
        }

        /***2***/
        testBoard->resetLifeBoard();
        testBoard->setLifeBoard(1, testBoard->getLifeBoardXRange() - 1, 0);
        copyBoard->copy(testBoard);
        if(!this->copyTestError(copyBoard, xRangeOfBoard, yRangeOfBoard)){
            copyBoard->~LifeBoard();
            return false;
        }

        /***3***/
        testBoard->resetLifeBoard();
        testBoard->setLifeBoard(1, 0, testBoard->getLifeBoardYRange() - 1);
        copyBoard->copy(testBoard);
        if(!this->copyTestError(copyBoard, xRangeOfBoard, yRangeOfBoard)){
            copyBoard->~LifeBoard();
            return false;
        }

        /***4***/
        testBoard->resetLifeBoard();
        testBoard->setLifeBoard(1, 0, 0);
        copyBoard->copy(testBoard);
        if(!this->copyTestError(copyBoard, xRangeOfBoard, yRangeOfBoard)){
            copyBoard->~LifeBoard();
            return false;
        }

        copyBoard->~LifeBoard();
        return true;
      }

      //runs through the double array in a lifeboard and displays values on the console
      void LifeBoardTest::displayBoard(){
        cout << "\n";

        for(int x = 0; x < testBoard->getLifeBoardXRange(); x++){
          for(int y = 0; y < testBoard->getLifeBoardYRange(); y++){
            cout << testBoard->getLifeBoardValue(x, y);
          }
          cout << endl;
        }

      }

    bool LifeBoardTest::setValueTestError(int expected, int xValue, int yValue){
        if(testBoard->getLifeBoardValue(xValue, yValue) != expected){
          cout << "SetValueTest Error: " << testBoard->getLifeBoardValue(xValue, yValue) << endl;
          cout << "X: " << xValue << "   Y: " << yValue << endl;
          return false;
        }

        return true;
    }

    bool LifeBoardTest::resetGridError(){
      for(int x = 0; x < testBoard->getLifeBoardXRange(); x++){
          for(int y = 0; y < testBoard->getLifeBoardYRange(); y++){
            if(testBoard->getLifeBoardValue(x, y) != 0){
              cout << "Value in error: " + testBoard->getLifeBoardValue(x, y);
              return false;
            }
          }
      }

      return true;
    }

    bool LifeBoardTest::returnYRangeCorrError(){
      if(testBoard->getLifeBoardYRange() != 4){
          return false;
      }

      return true;
    }

    bool LifeBoardTest::returnXRangeCorrError(){
      if(testBoard->getLifeBoardXRange() != 3){
         return false;
      }

      return true;
    }

    bool LifeBoardTest::copyTestError(LifeBoard * copyBoard, int xRangeOfBoard, int yRangeOfBoard){
        for(int x = 0; x < xRangeOfBoard; x++){
          for(int y = 0; y < yRangeOfBoard; y++){
            if(testBoard->getLifeBoardValue(x, y) != copyBoard->getLifeBoardValue(x, y)){
              return false;
            }
          }
        }

        return true;
    }

    void LifeBoardTest::fillLifeBoardOnes(){
      for(int x = 0; x < testBoard->getLifeBoardXRange(); x++){
          for(int y = 0; y < testBoard->getLifeBoardYRange(); y++){
            testBoard->setLifeBoard(1, x, y);
          }
        }
    }

    void LifeBoardTest::fillLifeBoardAlt(){
      int temp = 0;
      for(int x = 0; x < testBoard->getLifeBoardXRange(); x++){
        for(int y = 0; y < testBoard->getLifeBoardYRange(); y++){
          if(temp == 0){
            testBoard->setLifeBoard(1, x, y);
          }
          else{
            testBoard->setLifeBoard(0, x, y);
          }
        }
      }
    }
